/*
 * @Author: 熊志强
 * @Date: 2021-08-06 17:07:47
 * @Description:
 * 小程序增强工具
 * feat:  增加全局事件、属性插入功能 done
 * feat： 增加响应式功能  done
 * feat： 增加computed功能  done
 * feat： 增加watch功能  done
 * feat： 增加路由监听功能   todo
 * @FilePath: /wx-weapp/utils/enhancer/index.js
 */

import { isType } from "./utils/util";
import { initComputed, initData, initWatcher } from "./core/index";
import watcher from "./core/watcher";

export const Watcher = watcher;

const originMethods = { App, Page, Component, Behavior };
let isObserverData = false;
export default function (DeafultInspect = {}) {
  isObserverData = DeafultInspect.isObserverData;
  Object.keys(originMethods).forEach((method) => {
    rewriteWxMethods(method, DeafultInspect[method]);
  });
}

export { initComputed, initData, initWatcher };
export function initEnhance(vm, isObserverData) {
  initData && initData(vm, isObserverData);
  initWatcher && initWatcher(vm);
  initComputed && initComputed(vm);
}

/**
 * 重写小程序原始方法 App, Page, Component, Behavior
 * @param {String} method 方法名
 */
function rewriteWxMethods(method, inspect) {
  const copyMethod = getMewMethod(method, inspect);
  switch (method) {
    case "App":
      App = copyMethod;
      break;
    case "Page":
      Page = copyMethod;
      break;
    case "Component":
      Component = copyMethod;
      break;
    case "Behavior":
      Behavior = copyMethod;
      break;
    default:
      break;
  }
}

/**
 * 生成新的method
 * @param {string} method  method名称
 * @returns {Function}
 */
function getMewMethod(method, inspect = {}) {
  // ...生成新的methods
  return function (params = {}) {
    // routerListener.call(this,method, params)
    if (Object.keys(inspect).length) {
      addInspect(method, params, inspect);
    } else {
      addEnchers(method, params);
    }
    addComputedToData(params);
    originMethods[method](params);
  };
}

//将computed添加到data上，供模版使用
function addComputedToData(params) {
  if (params.computed) {
    let computedKeys = Object.keys(params.computed);
    computedKeys.forEach((ck) => {
      if (params.data) {
        params.data[ck] = "";
      }
    });
  }
}

//初始化增强器
function addEnchers(method, params) {
  let onLoadHooks = null;
  switch (method) {
    case "Page":
    case "Behavior":
      onLoadHooks = params.onLoad;
      break;
    case "Component":
      onLoadHooks = params.lifetimes?.attached;
      break;
    default:
      break;
  }
  let onLoadFunc = function (...args) {
    this.__proto__.params = params; //自定义组件上不能自定义属性，所以挂在实例的原型上
    initData && initData(this, isObserverData);
    initWatcher && initWatcher(this);
    initComputed && initComputed(this);
    onLoadHooks && onLoadHooks.apply(this, args);
  };
  //自定义组件
  if (method === "Component") {
    params.lifetimes = params.lifetimes || {};
    params.lifetimes.attached = onLoadFunc;
  } else {
    params.onLoad = onLoadFunc;
  }
}

//全局注入属性和方法
function addInspect(method, params, inspect) {
  const inspectArr = Object.keys(inspect);
  //克隆一份入参，防止递归调用
  const paramsClone = {};
  inspectArr.forEach((inspKey) => {
    paramsClone[inspKey] = params[inspKey];
    if (inspKey === "data") {
      params.data = { ...inspect[inspKey], ...params.data };
    } else if (
      inspKey.startsWith("on") &&
      isType(inspect[inspKey]) === "function"
    ) {
      params[inspKey] = function (...opts) {
        inspect[inspKey].apply(this, opts);
        paramsClone[inspKey] && paramsClone[inspKey].apply(this, opts);
      };
    } else if (inspKey === "methods") {
      params.methods = {
        ...inspect[inspKey],
        ...params.methods,
      };
    } else {
      params[inspKey] = inspect[inspKey];
    }
    addEnchers(method, params);
  });
}
